#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
默认凭据检测工具 - 修复版
版本: 1.1
功能: 检测系统中的默认账户/默认口令漏洞（修复SSH连接问题）

"""

import os
import sys
import requests
import urllib3
import json
import time
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
import re
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
import socket
import concurrent.futures
import shutil
from pathlib import Path
import signal
import psutil
import paramiko
from ftplib import FTP
from ftplib import error_perm
import smtplib
from imaplib import IMAP4
from poplib import POP3

# 禁用SSL证书验证警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class ProgressTracker:
    """进度跟踪器"""
    def __init__(self, total_steps):
        self.total_steps = total_steps
        self.current_step = 0
        self.start_time = time.time()
        self.lock = threading.Lock()  # 线程安全锁
    
    def update(self, step_name, current=0, total=0):
        """更新进度"""
        with self.lock:
            self.current_step += 1
            elapsed = time.time() - self.start_time
            progress = min(100.0, (self.current_step / self.total_steps) * 100)  # 限制在100%以内
            
            if total > 0:
                print(f"\r[进度: {progress:.1f}%] {step_name} ({current}/{total}) - 耗时: {elapsed:.1f}s", end='', flush=True)
            else:
                print(f"\r[进度: {progress:.1f}%] {step_name} - 耗时: {elapsed:.1f}s", end='', flush=True)

class DefaultCredentialTester:
    def __init__(self, target, threads=10):
        """
        初始化默认凭据检测器
        :param target: 目标地址 (URL或IP:端口)
        :param threads: 并发线程数
        """
        self.target = target
        self.threads = threads
        self.parsed_url = urlparse(target) if target.startswith(('http://', 'https://')) else None
        self.host = self.parsed_url.hostname if self.parsed_url else target.split(':')[0]
        self.port = self.parsed_url.port if self.parsed_url else (443 if target.startswith('https://') else 80 if target.startswith('http://') else 22)
        self.scheme = self.parsed_url.scheme if self.parsed_url else 'ssh'  # 默认为SSH
        self.session = requests.Session()
        self.session.verify = False
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        })
        self.results = {
            'web_vulnerabilities': [],
            'ssh_vulnerabilities': [],
            'ftp_vulnerabilities': [],
            'database_vulnerabilities': [],
            'email_vulnerabilities': [],
            'service_vulnerabilities': [],
            'vulnerability_summary': {},
            'recommendations': [],
            'scan_timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        self.progress = ProgressTracker(6)  # 总共6个步骤
        self.report_dir = f"default_credential_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        self.interrupted = False
        self.create_report_directory()
        
        # 设置信号处理
        signal.signal(signal.SIGINT, self.signal_handler)

    def signal_handler(self, signum, frame):
        """信号处理函数"""
        print(f"\n\n[!] 检测被用户中断...")
        self.interrupted = True
        print("[*] 正在保存当前结果...")
        sys.exit(0)

    def create_report_directory(self):
        """创建报告目录"""
        Path(self.report_dir).mkdir(exist_ok=True)
        print(f"[*] 报告目录已创建: {self.report_dir}")

    def check_port_open(self, host, port, timeout=3):
        """检查端口是否开放"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(timeout)
            result = sock.connect_ex((host, port))
            sock.close()
            return result == 0
        except:
            return False

    def check_web_auth(self):
        """检查Web应用默认凭据"""
        print(f"\n[*] 检查Web应用默认凭据...wait a moment")
        
        # Web应用默认凭据组合
        web_credentials = [
            # 常见Web管理后台
            ("admin", "admin"), ("admin", "password"), ("admin", "123456"),
            ("root", "root"), ("root", "password"), ("root", "toor"),
            ("user", "user"), ("guest", "guest"), ("test", "test"),
            ("admin", "admin123"), ("administrator", "admin"),
            ("webmaster", "webmaster"), ("manager", "manager"),
            ("sa", ""), ("sa", "sa"), ("postgres", "postgres"),
            ("mysql", ""), ("admin", "mysql"), ("root", ""),
        ]
        
        vulnerable_endpoints = []
        
        # 尝试访问需要认证的端点
        auth_required_endpoints = [
            "/admin", "/admin/", "/login", "/login/", "/dashboard", "/dashboard/",
            "/manage", "/manage/", "/backend", "/backend/", "/api/admin", "/api/admin/",
            "/phpmyadmin", "/phpmyadmin/", "/webmin", "/webmin/", "/cpanel", "/cpanel/",
            "/plesk", "/plesk/", "/joomla/administrator", "/wp-admin", "/wp-login.php"
        ]
        
        def check_web_endpoint(endpoint):
            if self.interrupted:
                return None
            try:
                full_url = urljoin(self.target, endpoint) if self.target.startswith(('http://', 'https://')) else f"http://{self.target}{endpoint}"
                
                for username, password in web_credentials:
                    if self.interrupted:
                        break
                    try:
                        # 尝试使用基本认证
                        response = self.session.get(full_url, 
                                                  auth=(username, password), 
                                                  timeout=10)
                        
                        if response.status_code in [200, 201, 202, 203, 204, 205, 206]:
                            # 检查响应内容是否包含管理界面特征
                            content = response.text.lower()
                            sensitive_indicators = [
                                'admin', 'dashboard', 'login', 'password', 'config', 'database',
                                'user', 'setting', 'management', 'console', 'panel', 'control'
                            ]
                            
                            has_sensitive_info = any(indicator in content for indicator in sensitive_indicators)
                            
                            if has_sensitive_info or len(content) > 100:
                                return {
                                    'url': full_url,
                                    'username': username,
                                    'password': password,
                                    'status_code': response.status_code,
                                    'type': 'web',
                                    'service': 'http'
                                }
                    except Exception:
                        continue
                return None
            except Exception:
                return None
        
        with ThreadPoolExecutor(max_workers=self.threads) as executor:
            futures = [executor.submit(check_web_endpoint, endpoint) for endpoint in auth_required_endpoints]
            
            completed = 0
            total_endpoints = len(auth_required_endpoints)
            
            for future in as_completed(futures):
                if self.interrupted:
                    for f in futures:
                        f.cancel()
                    break
                
                completed += 1
                self.progress.update("检查Web默认凭据", completed, total_endpoints)
                
                result = future.result()
                if result:
                    vulnerable_endpoints.append(result)
                    print(f"\n    [!] 发现Web默认凭据: {result['username']}:{result['password']} -> {result['url']}")
        
        print()  # 换行
        return vulnerable_endpoints

    def check_ssh_default_credentials(self):
        """检查SSH默认凭据 - 修复版本"""
        print(f"\n[*] 检查SSH默认凭据...")
        
        if not self.check_port_open(self.host, 22):
            print(f"    [-] SSH端口 (22) 未开放，跳过SSH检测")
            return []
        
        # SSH默认凭据组合
        ssh_credentials = [
            ("root", "root"), ("root", "password"), ("root", "toor"),
            ("admin", "admin"), ("admin", "password"), ("admin", "123456"),
            ("user", "user"), ("user", "password"), ("test", "test"),
            ("pi", "raspberry"), ("vagrant", "vagrant"), ("ubuntu", "ubuntu"),
            ("oracle", "oracle"), ("postgres", "postgres"), ("mysql", "mysql"),
            ("guest", "guest"), ("support", "support"), ("service", "service"),
            ("backup", "backup"), ("monitor", "monitor"), ("operator", "operator"),
            ("maint", "maint"), ("maint", "password"), ("sysadmin", "sysadmin"),
            ("sysadmin", "password"), ("admin", "admin123"), ("root", "123456"),
            ("root", "admin"), ("admin", "root"), ("root", "password123"),
            ("root", "12345"), ("root", "0000"), ("root", "1111"), ("root", "1234"),
            ("admin", "1234"), ("admin", "0000"), ("admin", "1111"), ("admin", "12345"),
            ("user", "123456"), ("guest", "123456"), ("test", "123456")
        ]
        
        vulnerable_ssh = []
        
        def check_ssh_credential(username, password):
            if self.interrupted:
                return None
            try:
                # 创建SSH客户端，设置超时和重试机制
                ssh = paramiko.SSHClient()
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                
                # 尝试连接，设置较短的超时时间
                ssh.connect(
                    self.host, 
                    port=22, 
                    username=username, 
                    password=password, 
                    timeout=8,  # 减少超时时间
                    banner_timeout=5,  # 设置banner超时
                    auth_timeout=5    # 设置认证超时
                )
                
                # 如果连接成功，关闭连接并返回结果
                ssh.close()
                
                return {
                    'host': self.host,
                    'port': 22,
                    'username': username,
                    'password': password,
                    'type': 'ssh',
                    'service': 'ssh'
                }
            except paramiko.AuthenticationException:
                # 认证失败，返回None
                return None
            except paramiko.SSHException as e:
                # SSH协议错误，可能是Invalid packet blocking
                if "Invalid packet blocking" in str(e) or "timeout" in str(e).lower():
                    # 这种情况可能表示服务不稳定，跳过
                    return None
                else:
                    # 其他SSH错误，返回None
                    return None
            except Exception:
                # 其他异常，返回None
                return None
        
        with ThreadPoolExecutor(max_workers=3) as executor:  # 减少SSH并发数，避免连接问题
            futures = [executor.submit(check_ssh_credential, cred[0], cred[1]) for cred in ssh_credentials]
            
            completed = 0
            total_credentials = len(ssh_credentials)
            
            for future in as_completed(futures):
                if self.interrupted:
                    for f in futures:
                        f.cancel()
                    break
                
                completed += 1
                self.progress.update("检查SSH默认凭据", completed, total_credentials)
                
                result = future.result()
                if result:
                    vulnerable_ssh.append(result)
                    print(f"\n    [!] 发现SSH默认凭据: {result['username']}:{result['password']}@{result['host']}")
        
        print()  # 换行
        return vulnerable_ssh

    def check_ftp_default_credentials(self):
        """检查FTP默认凭据"""
        print(f"\n[*] 检查FTP默认凭据...")
        
        if not self.check_port_open(self.host, 21):
            print(f"    [-] FTP端口 (21) 未开放，跳过FTP检测")
            return []
        
        # FTP默认凭据组合
        ftp_credentials = [
            ("anonymous", ""), ("ftp", "ftp"), ("admin", "admin"),
            ("admin", "password"), ("root", "root"), ("user", "user"),
            ("test", "test"), ("guest", "guest"), ("upload", "upload"),
            ("download", "download"), ("web", "web"), ("backup", "backup"),
            ("admin", "123456"), ("root", "123456"), ("user", "123456"),
            ("ftp", "password"), ("anonymous", "anonymous"), ("ftp", ""),
            ("admin", ""), ("root", ""), ("user", ""), ("test", ""),
            ("guest", ""), ("web", "web"), ("www", "www"), ("nobody", "nobody")
        ]
        
        vulnerable_ftp = []
        
        def check_ftp_credential(username, password):
            if self.interrupted:
                return None
            try:
                ftp = FTP()
                ftp.connect(self.host, 21, timeout=10)
                ftp.login(username, password)
                ftp.quit()
                
                return {
                    'host': self.host,
                    'port': 21,
                    'username': username,
                    'password': password,
                    'type': 'ftp',
                    'service': 'ftp'
                }
            except error_perm:
                return None
            except Exception:
                return None
        
        with ThreadPoolExecutor(max_workers=2) as executor:  # FTP连接限制并发数
            futures = [executor.submit(check_ftp_credential, cred[0], cred[1]) for cred in ftp_credentials]
            
            completed = 0
            total_credentials = len(ftp_credentials)
            
            for future in as_completed(futures):
                if self.interrupted:
                    for f in futures:
                        f.cancel()
                    break
                
                completed += 1
                self.progress.update("检查FTP默认凭据", completed, total_credentials)
                
                result = future.result()
                if result:
                    vulnerable_ftp.append(result)
                    print(f"\n    [!] 发现FTP默认凭据: {result['username']}:{result['password']}@{result['host']}")
        
        print()  # 换行
        return vulnerable_ftp

    def check_database_default_credentials(self):
        """检查数据库默认凭据"""
        print(f"\n[*] 检查数据库默认凭据...")
        
        vulnerable_db = []
        
        # 检查MySQL
        if self.check_port_open(self.host, 3306):
            print(f"    [*] 检查MySQL默认凭据...")
            mysql_credentials = [
                ("root", ""), ("root", "root"), ("root", "password"),
                ("admin", "admin"), ("admin", "password"), ("mysql", "mysql"),
                ("user", "user"), ("test", "test"), ("root", "123456"),
                ("admin", "123456"), ("user", "password"), ("root", "toor")
            ]
            
            try:
                import pymysql
                for username, password in mysql_credentials:
                    if self.interrupted:
                        break
                    try:
                        conn = pymysql.connect(
                            host=self.host,
                            port=3306,
                            user=username,
                            password=password,
                            connect_timeout=10
                        )
                        conn.close()
                        
                        result = {
                            'host': self.host,
                            'port': 3306,
                            'username': username,
                            'password': password,
                            'type': 'database',
                            'service': 'mysql'
                        }
                        vulnerable_db.append(result)
                        print(f"\n    [!] 发现MySQL默认凭据: {username}:{password}@{self.host}:3306")
                    except:
                        continue
            except ImportError:
                print(f"    [-] 未安装pymysql，跳过MySQL检测")
        
        # 检查PostgreSQL
        if self.check_port_open(self.host, 5432):
            print(f"    [*] 检查PostgreSQL默认凭据...")
            pg_credentials = [
                ("postgres", "postgres"), ("postgres", "password"),
                ("admin", "admin"), ("admin", "password"), ("postgres", ""),
                ("user", "user"), ("test", "test"), ("postgres", "123456"),
                ("admin", "123456"), ("user", "password")
            ]
            
            try:
                import psycopg2
                for username, password in pg_credentials:
                    if self.interrupted:
                        break
                    try:
                        conn = psycopg2.connect(
                            host=self.host,
                            port=5432,
                            user=username,
                            password=password,
                            connect_timeout=10
                        )
                        conn.close()
                        
                        result = {
                            'host': self.host,
                            'port': 5432,
                            'username': username,
                            'password': password,
                            'type': 'database',
                            'service': 'postgresql'
                        }
                        vulnerable_db.append(result)
                        print(f"\n    [!] 发现PostgreSQL默认凭据: {username}:{password}@{self.host}:5432")
                    except:
                        continue
            except ImportError:
                print(f"    [-] 未安装psycopg2，跳过PostgreSQL检测")
        
        # 检查MongoDB
        if self.check_port_open(self.host, 27017):
            print(f"    [*] 检查MongoDB默认凭据...")
            mongo_credentials = [
                ("admin", "admin"), ("admin", "password"), ("root", "root"),
                ("root", "password"), ("user", "user"), ("test", "test"),
                ("admin", "123456"), ("root", "123456"), ("user", "password")
            ]
            
            try:
                import pymongo
                for username, password in mongo_credentials:
                    if self.interrupted:
                        break
                    try:
                        client = pymongo.MongoClient(self.host, 27017, serverSelectionTimeoutMS=10000)
                        client.admin.authenticate(username, password)
                        client.close()
                        
                        result = {
                            'host': self.host,
                            'port': 27017,
                            'username': username,
                            'password': password,
                            'type': 'database',
                            'service': 'mongodb'
                        }
                        vulnerable_db.append(result)
                        print(f"\n    [!] 发现MongoDB默认凭据: {username}:{password}@{self.host}:27017")
                    except:
                        continue
            except ImportError:
                print(f"    [-] 未安装pymongo，跳过MongoDB检测")
        
        print()  # 换行
        return vulnerable_db

    def check_email_default_credentials(self):
        """检查邮件服务默认凭据"""
        print(f"\n[*] 检查邮件服务默认凭据...")
        
        vulnerable_email = []
        
        # 检查SMTP
        if self.check_port_open(self.host, 25):
            print(f"    [*] 检查SMTP默认凭据...")
            smtp_credentials = [
                ("admin", "admin"), ("admin", "password"), ("user", "user"),
                ("test", "test"), ("admin", "123456"), ("user", "password")
            ]
            
            for username, password in smtp_credentials:
                if self.interrupted:
                    break
                try:
                    server = smtplib.SMTP(self.host, 25, timeout=10)
                    server.starttls()
                    server.login(username, password)
                    server.quit()
                    
                    result = {
                        'host': self.host,
                        'port': 25,
                        'username': username,
                        'password': password,
                        'type': 'email',
                        'service': 'smtp'
                    }
                    vulnerable_email.append(result)
                    print(f"\n    [!] 发现SMTP默认凭据: {username}:{password}@{self.host}:25")
                    break  # 找到一个就继续
                except:
                    continue
        
        # 检查IMAP
        if self.check_port_open(self.host, 143):
            print(f"    [*] 检查IMAP默认凭据...")
            imap_credentials = [
                ("admin", "admin"), ("admin", "password"), ("user", "user"),
                ("test", "test"), ("admin", "123456"), ("user", "password")
            ]
            
            for username, password in imap_credentials:
                if self.interrupted:
                    break
                try:
                    server = IMAP4(self.host, 143)
                    server.login(username, password)
                    server.logout()
                    
                    result = {
                        'host': self.host,
                        'port': 143,
                        'username': username,
                        'password': password,
                        'type': 'email',
                        'service': 'imap'
                    }
                    vulnerable_email.append(result)
                    print(f"\n    [!] 发现IMAP默认凭据: {username}:{password}@{self.host}:143")
                    break  # 找到一个就继续
                except:
                    continue
        
        # 检查POP3
        if self.check_port_open(self.host, 110):
            print(f"    [*] 检查POP3默认凭据...")
            pop3_credentials = [
                ("admin", "admin"), ("admin", "password"), ("user", "user"),
                ("test", "test"), ("admin", "123456"), ("user", "password")
            ]
            
            for username, password in pop3_credentials:
                if self.interrupted:
                    break
                try:
                    server = POP3(self.host, 110)
                    server.user(username)
                    server.pass_(password)
                    server.quit()
                    
                    result = {
                        'host': self.host,
                        'port': 110,
                        'username': username,
                        'password': password,
                        'type': 'email',
                        'service': 'pop3'
                    }
                    vulnerable_email.append(result)
                    print(f"\n    [!] 发现POP3默认凭据: {username}:{password}@{self.host}:110")
                    break  # 找到一个就继续
                except:
                    continue
        
        print()  # 换行
        return vulnerable_email

    def check_common_service_default_credentials(self):
        """检查常见服务默认凭据"""
        print(f"\n[*] 检查常见服务默认凭据...")
        
        vulnerable_services = []
        
        # 检查Telnet (23)
        if self.check_port_open(self.host, 23):
            print(f"    [*] 检查Telnet默认凭据...")
            telnet_credentials = [
                ("admin", "admin"), ("admin", "password"), ("root", "root"),
                ("root", "password"), ("user", "user"), ("test", "test"),
                ("admin", "123456"), ("root", "123456"), ("user", "password")
            ]
            
            try:
                import telnetlib
                for username, password in telnet_credentials:
                    if self.interrupted:
                        break
                    try:
                        tn = telnetlib.Telnet(self.host, 23, timeout=10)
                        tn.read_until(b"login:", timeout=5)
                        tn.write(username.encode('ascii') + b"\n")
                        tn.read_until(b"Password:", timeout=5)
                        tn.write(password.encode('ascii') + b"\n")
                        
                        # 尝试读取响应，如果成功登录通常会有提示符
                        response = tn.read_very_eager()
                        tn.close()
                        
                        if b"$" in response or b"#" in response or b">" in response:
                            result = {
                                'host': self.host,
                                'port': 23,
                                'username': username,
                                'password': password,
                                'type': 'service',
                                'service': 'telnet'
                            }
                            vulnerable_services.append(result)
                            print(f"\n    [!] 发现Telnet默认凭据: {username}:{password}@{self.host}:23")
                            break
                    except:
                        continue
            except ImportError:
                print(f"    [-] 未安装telnetlib相关模块，跳过Telnet检测")
        
        # 检查Redis (6379)
        if self.check_port_open(self.host, 6379):
            print(f"    [*] 检查Redis默认凭据...")
            try:
                import redis
                try:
                    r = redis.Redis(host=self.host, port=6379, db=0, socket_timeout=10)
                    r.ping()
                    
                    result = {
                        'host': self.host,
                        'port': 6379,
                        'username': 'no_auth_required',
                        'password': 'no_password',
                        'type': 'service',
                        'service': 'redis'
                    }
                    vulnerable_services.append(result)
                    print(f"\n    [!] 发现Redis无认证: {self.host}:6379")
                except:
                    # 尝试默认密码
                    redis_passwords = ["", "redis", "password", "123456", "admin"]
                    for password in redis_passwords:
                        if self.interrupted:
                            break
                        try:
                            r = redis.Redis(host=self.host, port=6379, db=0, password=password, socket_timeout=10)
                            r.ping()
                            
                            result = {
                                'host': self.host,
                                'port': 6379,
                                'username': 'redis',
                                'password': password,
                                'type': 'service',
                                'service': 'redis'
                            }
                            vulnerable_services.append(result)
                            print(f"\n    [!] 发现Redis默认凭据: redis:{password}@{self.host}:6379")
                            break
                        except:
                            continue
            except ImportError:
                print(f"    [-] 未安装redis模块，跳过Redis检测")
        
        # 检查Elasticsearch (9200)
        if self.check_port_open(self.host, 9200):
            print(f"    [*] 检查Elasticsearch默认凭据...")
            try:
                response = requests.get(f"http://{self.host}:9200/_cat/health", timeout=10)
                if response.status_code == 200:
                    result = {
                        'host': self.host,
                        'port': 9200,
                        'username': 'no_auth_required',
                        'password': 'no_password',
                        'type': 'service',
                        'service': 'elasticsearch'
                    }
                    vulnerable_services.append(result)
                    print(f"\n    [!] 发现Elasticsearch无认证: {self.host}:9200")
            except:
                pass
        
        print()  # 换行
        return vulnerable_services

    def run_comprehensive_test(self):
        """运行综合测试"""
        print(f"\n[*] 开始综合默认凭据检测: {self.target}")
        print("="*60)
        
        try:
            # 1. 检查Web应用默认凭据
            web_vulns = self.check_web_auth()
            if not self.interrupted:
                self.results['web_vulnerabilities'] = web_vulns
                self.progress.update("检查Web默认凭据")
        
            # 2. 检查SSH默认凭据
            ssh_vulns = self.check_ssh_default_credentials()
            if not self.interrupted:
                self.results['ssh_vulnerabilities'] = ssh_vulns
                self.progress.update("检查SSH默认凭据")
        
            # 3. 检查FTP默认凭据
            ftp_vulns = self.check_ftp_default_credentials()
            if not self.interrupted:
                self.results['ftp_vulnerabilities'] = ftp_vulns
                self.progress.update("检查FTP默认凭据")
        
            # 4. 检查数据库默认凭据
            db_vulns = self.check_database_default_credentials()
            if not self.interrupted:
                self.results['database_vulnerabilities'] = db_vulns
                self.progress.update("检查数据库默认凭据")
        
            # 5. 检查邮件服务默认凭据
            email_vulns = self.check_email_default_credentials()
            if not self.interrupted:
                self.results['email_vulnerabilities'] = email_vulns
                self.progress.update("检查邮件服务默认凭据")
        
            # 6. 检查常见服务默认凭据
            service_vulns = self.check_common_service_default_credentials()
            if not self.interrupted:
                self.results['service_vulnerabilities'] = service_vulns
                self.progress.update("检查常见服务默认凭据")
        
            # 汇总结果
            if not self.interrupted:
                self.results['vulnerability_summary'] = self.generate_summary()
                self.results['recommendations'] = self.generate_recommendations()
                self.results['scan_timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        
                return self.results
            else:
                print("\n[!] 扫描被中断，返回部分结果...")
                self.results['vulnerability_summary'] = self.generate_summary()
                self.results['recommendations'] = self.generate_recommendations()
                self.results['scan_timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                return self.results
                
        except KeyboardInterrupt:
            print("\n[!] 检测被用户中断...")
            self.results['vulnerability_summary'] = self.generate_summary()
            self.results['recommendations'] = self.generate_recommendations()
            self.results['scan_timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            return self.results

    def generate_summary(self):
        """生成漏洞摘要"""
        summary = {
            'web_vulnerabilities': len(self.results.get('web_vulnerabilities', [])),
            'ssh_vulnerabilities': len(self.results.get('ssh_vulnerabilities', [])),
            'ftp_vulnerabilities': len(self.results.get('ftp_vulnerabilities', [])),
            'database_vulnerabilities': len(self.results.get('database_vulnerabilities', [])),
            'email_vulnerabilities': len(self.results.get('email_vulnerabilities', [])),
            'service_vulnerabilities': len(self.results.get('service_vulnerabilities', [])),
            'total_vulnerabilities': sum([
                len(self.results.get('web_vulnerabilities', [])),
                len(self.results.get('ssh_vulnerabilities', [])),
                len(self.results.get('ftp_vulnerabilities', [])),
                len(self.results.get('database_vulnerabilities', [])),
                len(self.results.get('email_vulnerabilities', [])),
                len(self.results.get('service_vulnerabilities', []))
            ])
        }
        
        return summary

    def generate_recommendations(self):
        """生成安全建议"""
        recommendations = [
            "1. 立即更改所有默认账户的密码",
            "2. 禁用或删除不必要的默认账户",
            "3. 实施强密码策略（至少8位，包含大小写字母、数字、特殊字符）",
            "4. 启用账户锁定机制（多次失败后锁定）",
            "5. 实施多因素认证（MFA）",
            "6. 定期轮换密码（建议每90天）",
            "7. 限制默认账户的权限（最小权限原则）",
            "8. 禁用不必要的服务和端口",
            "9. 实施网络访问控制（防火墙规则）",
            "10. 定期进行安全审计和渗透测试"
        ]
        
        return recommendations

    def save_detailed_report(self):
        """保存详细报告到文件"""
        if not os.path.exists(self.report_dir):
            Path(self.report_dir).mkdir(exist_ok=True)
        
        report_file = f"{self.report_dir}/default_credential_report.json"
        
        # 保存完整的JSON报告
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(self.results, f, indent=2, ensure_ascii=False)
        
        # 生成人类可读的报告
        readable_report = f"{self.report_dir}/default_credential_report.txt"
        with open(readable_report, 'w', encoding='utf-8') as f:
            f.write("="*60 + "\n")
            f.write("默认凭据检测详细报告\n")
            f.write("="*60 + "\n")
            f.write(f"目标地址: {self.target}\n")
            f.write(f"检测时间: {self.results.get('scan_timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))}\n")
            f.write(f"报告目录: {self.report_dir}\n")
            f.write(f"中断状态: {'是' if self.interrupted else '否'}\n")
            f.write("\n")
            
            # 摘要信息
            summary = self.results.get('vulnerability_summary', {})
            f.write("漏洞摘要:\n")
            f.write("-" * 40 + "\n")
            f.write(f"Web应用漏洞: {summary.get('web_vulnerabilities', 0)}\n")
            f.write(f"SSH服务漏洞: {summary.get('ssh_vulnerabilities', 0)}\n")
            f.write(f"FTP服务漏洞: {summary.get('ftp_vulnerabilities', 0)}\n")
            f.write(f"数据库漏洞: {summary.get('database_vulnerabilities', 0)}\n")
            f.write(f"邮件服务漏洞: {summary.get('email_vulnerabilities', 0)}\n")
            f.write(f"其他服务漏洞: {summary.get('service_vulnerabilities', 0)}\n")
            f.write(f"总漏洞数: {summary.get('total_vulnerabilities', 0)}\n")
            f.write("\n")
            
            # 详细结果
            f.write("详细检测结果:\n")
            f.write("-" * 40 + "\n")
            
            # Web应用漏洞
            web_vulns = self.results.get('web_vulnerabilities', [])
            if web_vulns:
                f.write("\nWeb应用漏洞:\n")
                for vuln in web_vulns:
                    f.write(f"  • {vuln['url']} - {vuln['username']}:{vuln['password']} ({vuln['status_code']})\n")
            
            # SSH漏洞
            ssh_vulns = self.results.get('ssh_vulnerabilities', [])
            if ssh_vulns:
                f.write("\nSSH服务漏洞:\n")
                for vuln in ssh_vulns:
                    f.write(f"  • {vuln['host']}:{vuln['port']} - {vuln['username']}:{vuln['password']}\n")
            
            # FTP漏洞
            ftp_vulns = self.results.get('ftp_vulnerabilities', [])
            if ftp_vulns:
                f.write("\nFTP服务漏洞:\n")
                for vuln in ftp_vulns:
                    f.write(f"  • {vuln['host']}:{vuln['port']} - {vuln['username']}:{vuln['password']}\n")
            
            # 数据库漏洞
            db_vulns = self.results.get('database_vulnerabilities', [])
            if db_vulns:
                f.write("\n数据库漏洞:\n")
                for vuln in db_vulns:
                    f.write(f"  • {vuln['host']}:{vuln['port']} - {vuln['username']}:{vuln['password']} ({vuln['service']})\n")
            
            # 邮件服务漏洞
            email_vulns = self.results.get('email_vulnerabilities', [])
            if email_vulns:
                f.write("\n邮件服务漏洞:\n")
                for vuln in email_vulns:
                    f.write(f"  • {vuln['host']}:{vuln['port']} - {vuln['username']}:{vuln['password']} ({vuln['service']})\n")
            
            # 其他服务漏洞
            service_vulns = self.results.get('service_vulnerabilities', [])
            if service_vulns:
                f.write("\n其他服务漏洞:\n")
                for vuln in service_vulns:
                    f.write(f"  • {vuln['host']}:{vuln['port']} - {vuln['username']}:{vuln['password']} ({vuln['service']})\n")
            
            # 安全建议
            f.write("\n安全建议:\n")
            f.write("-" * 40 + "\n")
            for rec in self.results.get('recommendations', self.generate_recommendations()):
                f.write(f"• {rec}\n")
            
            f.write("="*60 + "\n")
        
        print(f"\n[+] 详细报告已保存至: {self.report_dir}/")
        print(f"    - JSON格式: default_credential_report.json")
        print(f"    - 文本格式: default_credential_report.txt")

    def print_summary_report(self):
        """打印摘要报告"""
        print("\n" + "="*60)
        print("默认凭据检测摘要报告")
        print("="*60)
        print(f"目标地址: {self.target}")
        print(f"检测时间: {self.results.get('scan_timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))}")
        print(f"报告目录: {self.report_dir}")
        print(f"中断状态: {'是' if self.interrupted else '否'}")
        print()
        
        # 摘要信息
        summary = self.results.get('vulnerability_summary', {})
        print("漏洞摘要:")
        print("-" * 40)
        print(f"Web应用漏洞: {summary.get('web_vulnerabilities', 0)}")
        print(f"SSH服务漏洞: {summary.get('ssh_vulnerabilities', 0)}")
        print(f"FTP服务漏洞: {summary.get('ftp_vulnerabilities', 0)}")
        print(f"数据库漏洞: {summary.get('database_vulnerabilities', 0)}")
        print(f"邮件服务漏洞: {summary.get('email_vulnerabilities', 0)}")
        print(f"其他服务漏洞: {summary.get('service_vulnerabilities', 0)}")
        print(f"总漏洞数: {summary.get('total_vulnerabilities', 0)}")
        print()
        
        # 总体评估
        total_vulns = summary.get('total_vulnerabilities', 0)
        
        if total_vulns == 0:
            risk_level = "✅ 低风险 - 未发现默认凭据漏洞"
        elif total_vulns <= 3:
            risk_level = "⚠️  中等风险 - 存在少量默认凭据漏洞"
        elif total_vulns <= 8:
            risk_level = "🚨 高风险 - 存在多个默认凭据漏洞"
        else:
            risk_level = "🔥 严重风险 - 存在大量默认凭据漏洞"
        
        print(f"总体风险评估: {risk_level}")
        print(f"总发现漏洞数: {total_vulns}")
        
        if self.interrupted:
            print("⚠️  检测被中断 - 结果可能不完整")
        
        print("="*60)

def get_optimal_threads():
    """获取最优并发数"""
    try:
        import os
        import psutil
        
        # 获取系统信息
        cpu_count = os.cpu_count()
        memory_gb = psutil.virtual_memory().total / (1024**3)
        
        # 基于CPU和内存计算最优并发数
        optimal = min(
            cpu_count * 2,  # CPU核心数的2倍
            int(memory_gb * 10),  # 内存GB数 * 10
            20  # 上限20
        )
        
        return max(5, optimal)  # 至少5个，最多optimal个
    except:
        return 10  # 默认10个

def main():
    """主函数"""
    print("""
    ===========================================
    |    默认凭据检测工具 v1.1                |
    |  修复版 - 解决SSH连接问题               |
    ===========================================
    """)
    
    print("⚠️  警告: 此工具仅用于授权安全测试!")
    print("请确保您有权限测试目标系统\n")
    
    target = input("[+] 请输入目标地址 (如: https://example.com 或 192.168.1.1): ").strip()
    
    if not target:
        print("[!] 目标地址不能为空")
        return
    
    # 自动计算最优并发数
    try:
        optimal_threads = get_optimal_threads()
        
        print(f"[*] 检测到CPU核心数: {os.cpu_count()}")
        print(f"[*] 检测到内存大小: {psutil.virtual_memory().total / (1024**3):.1f}GB")
        print(f"[*] 推荐并发线程数: {optimal_threads}")
        
        threads_input = input(f"[+] 请输入并发线程数 (默认{optimal_threads}, 最大30): ").strip()
        if threads_input:
            threads = min(int(threads_input), 30)
        else:
            threads = optimal_threads
    except:
        # 如果无法获取系统信息，使用默认值
        threads = 10
    
    print(f"\n[*] 开始检测...")
    print(f"[*] 目标: {target}")
    print(f"[*] 线程数: {threads}")
    print(f"[*] 按 Ctrl+C 可随时中断检测")
    
    # 创建检测器并运行测试
    tester = DefaultCredentialTester(target, threads)
    results = tester.run_comprehensive_test()
    
    # 打印摘要报告
    tester.print_summary_report()
    
    # 保存详细报告
    tester.save_detailed_report()
    
    print(f"\n[*] 检测完成! 详细报告已生成在: {tester.report_dir}/")

if __name__ == "__main__":
    main()